package com.situ.skymallimageapi.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class Config implements WebMvcConfigurer {
    @Value("${upload.location}")
    private String uploadLocation;

    /**
     * 自定义json序列化器
     *
     * @return 自定义json序列化器
     */
    @Bean
    public Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer() {
        //克隆一个新的ObjectMapper实例
        ObjectMapper om = new ObjectMapper();
        //添加对jdk8日期类型的支持，需要在pom文件中引入jackson-datatype-jsr310，spring-boot-starter-web已默认引入
        om.registerModule(new JavaTimeModule());
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        //必须进行以下配置，否则会出现java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to xxx的异常
        //详见：https://knife.blog.csdn.net/article/details/122427607
        //配置在序列化时，将类型序列化到json中，所以能在反序列化时，自动根据类型进行反序列化
        om.activateDefaultTyping(om.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
        //配置对于无法反序列化的字段，不报错。比如有getter方法，但无setter方法或者无对应字段，则在反序列化时，不报错
        om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

        //使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值（默认使用JDK的序列化方式：JdkSerializationRedisSerializer）
        return new Jackson2JsonRedisSerializer<>(om, Object.class);
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory, Jackson2JsonRedisSerializer<Object> valueSerializer) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        redisTemplate.setValueSerializer(valueSerializer);
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }


    //将上传的目录映射为静态资源目录
    @Configuration
    public class WebMvcConfig implements WebMvcConfigurer {

        @Value("${upload.location}")
        private String uploadLocation;

        @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {
            // 请求映射到本地文件
            String location = "file:" + uploadLocation + "/images";
            registry.addResourceHandler("/images/**")
                    .addResourceLocations(location);
        }
    }
}
